package org.swim.core.manager;

import java.util.List;

import javax.ejb.Stateless;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig;

import org.swim.core.entities.Friendship;
import org.swim.core.entities.User;
import org.swim.local.manager.FriendshipManagerLocal;
import org.swim.remote.entities.IFriendship;
import org.swim.remote.entities.IFriendship.Status;
import org.swim.remote.entities.INotification.NotificationStatus;
import org.swim.remote.exceptions.FriendshipException;
import org.swim.remote.exceptions.SwimException;
import org.swim.remote.exceptions.TokenException;
import org.swim.remote.manager.FriendshipManagerRemote;

@Stateless
public class FriendshipManager extends SwimManager implements
		FriendshipManagerRemote, FriendshipManagerLocal {

	private static JsonConfig FRIENDSHIP_JSON_CFG;

	static {
		FRIENDSHIP_JSON_CFG = new JsonConfig();
		FRIENDSHIP_JSON_CFG.setRootClass(Friendship.class);
	}

	@PersistenceContext(unitName = "swimds")
	private EntityManager em;

	public IFriendship post(JSONObject json) {
		Friendship friendship = (Friendship) JSONSerializer.toJava(
				json.getJSONObject("friendship"), FRIENDSHIP_JSON_CFG);

		em.persist(friendship);

		return friendship;
	}

	public IFriendship delete(Integer id) {
		Query q = em.createQuery("SELECT f FROM Friendship f WHERE f.id = '"
				+ id + "'");
		Friendship friendship = (Friendship) q.getSingleResult();
		em.remove(friendship);
		return friendship;
	}

	public IFriendship put(JSONObject json) {
		Friendship friendship = (Friendship) JSONSerializer.toJava(json,
				FRIENDSHIP_JSON_CFG);
		em.merge(friendship);

		return friendship;
	}

	public IFriendship get(Integer id) {
		Query q = em.createQuery("SELECT f FROM Friendship f WHERE f.id = '"
				+ id + "'");
		return (Friendship) q.getSingleResult();
	}

	@SuppressWarnings("unchecked")
	public List<IFriendship> getAll() {
		Query q = em.createQuery("SELECT f FROM Friendship f");
		return q.getResultList();
	}

	public IFriendship requestFriendship(JSONObject object)
			throws NamingException, SwimException {
		String tokenUser = object.getString("token");

		Integer idSender = UserLogged.getUserLogged()
				.checkUserLogged(tokenUser);

		Integer idReceiver = object.getInt("receiverUserId");

		Query q = em
				.createQuery("SELECT f FROM Friendship f WHERE (f.userBySenderId = '"
						+ idReceiver
						+ "' and f.userByReceiverId = '"
						+ idSender
						+ "') "
						+ "or  (f.userBySenderId = '"
						+ idSender
						+ "' and f.userByReceiverId = '"
						+ idReceiver + "')");
		
		if (q.getResultList().size() != 0)
		{
			Friendship friendshipOld = (Friendship) q.getSingleResult();
			if(friendshipOld.getStatus() != Status.REJECTED)
				throw new FriendshipException("FRIENDSHIP ALREADY EXIST");
			else
			{
				em.remove(friendshipOld);
			}
				
		}
		
		User userBySenderId = (User) getUml().get(idSender);
		User userByReceiverId = (User) getUml().get(idReceiver);
		
		Friendship friendship = new Friendship(userBySenderId, userByReceiverId,
					IFriendship.Status.REQUESTED);
	
		em.persist(friendship);

		return friendship;
	}

	public IFriendship setStatusFriendship(JSONObject object)
			throws TokenException, FriendshipException {
		String tokenUser = object.getString("token");

		Integer idUser = UserLogged.getUserLogged().checkUserLogged(tokenUser);

		Integer idFriendship = object.getInt("friendshipId");

		Query q = em
				.createQuery("SELECT f FROM Friendship f WHERE f.userByReceiverId = '"
						+ idUser
						+ "' and f.id = '"
						+ idFriendship
						+ "' "
						+ "and f.status = '"
						+ IFriendship.Status.REQUESTED
						+ "'");

		if (q.getResultList().size() == 0)
			throw new FriendshipException("FRIENDSHIP'S REQUEST DOESN'T EXIST");

		Friendship friendship = (Friendship) q.getSingleResult();

		Status status = Status
				.valueOf(object.getString("status").toUpperCase());

		friendship.setStatus(status);

		em.merge(friendship);

		return friendship;
	}

	public IFriendship setStatusFriendshipNotification(JSONObject object)
			throws TokenException, FriendshipException {

		String tokenUser = object.getString("token");

		UserLogged.getUserLogged().checkUserLogged(tokenUser);

		Integer idFriendship = object.getInt("id");
		NotificationStatus notificationStatus = NotificationStatus
				.valueOf(object.getString("status"));
		//***********************************//
		Friendship friendship = em.find(Friendship.class, idFriendship);
		friendship.setNotificationStatus(notificationStatus);
		em.merge(friendship);
		//***********************************//

		// Query q = em.createQuery("SELECT f FROM Friendship f WHERE f.id = '"
		// + idFriendship + "' and f.notificationStatus = '"
		// + NotificationStatus.UNREAD + "'");
		//
		// if (q.getResultList().size() != 1) {
		// throw new FriendshipException("FRIENDSHIP DATA ERROR",
		// Severity.ERROR);
		// }
		//
		// NotificationStatus notificationStatus = NotificationStatus
		// .valueOf(object.getString("status"));
		//
		// Friendship friendship = (Friendship) q.getSingleResult();
		//
		// friendship.setNotificationStatus(notificationStatus);
		//
		// em.merge(friendship);

		return friendship;
	}

}
